#include "MaterialManager.h"
#include "Renderer.h"
#include "ShaderProgramManager.h"

namespace Nezha
{

	MaterialManager::~MaterialManager()
	{
		for(int i = 0; i < DST_NUM; i++)
		{
			mDefaultMats[i].release();
		}
	}

	MaterialPtr MaterialManager::findMaterial(const _string& name)
	{
		MaterialPtr mat;

		MaterialNameMap::iterator it = mMaterialMap.find(name);

		if(it != mMaterialMap.end())
		{
			return it->second;
		}

		return mat;
	}

	MaterialPtr MaterialManager::createMaterial(const _string& scriptName)
	{
		MaterialPtr mat;

		// TODO

		return mat;
	}

	MaterialPtr MaterialManager::createDefaultMaterial(DefaultShaderType dst)
	{
		MaterialPtr mat;

		if(mDefaultMats[dst].notNull())
		{
			mat = cloneMaterial(mDefaultMats[dst]);
		}
		else
		{
			char tmp[64] = {0};
			sprintf(tmp, "NezhaDefaultMaterial_%d", (int)dst);

			Material* newMat = NZ_New Material(tmp);

			ShaderProgramPtr defShader = Renderer::GetGlobal()->getShaderProgramManager()->createShader(dst);
			RenderPass* rp = newMat->createPass(tmp, defShader);

			mDefaultMats[dst] = newMat;
			mat = newMat;
		}

		return mat;
	}

	MaterialPtr MaterialManager::cloneMaterial(const MaterialPtr& matTemplate)
	{
		MaterialPtr mat;

		if(matTemplate.ptr())
		{
			_string cloneOneName = matTemplate->getName();
			cloneOneName += "_cloned";

			Material* newMat = NZ_New Material(cloneOneName);

			// this is dirty!!, but it is expensive to get a non-const version material using findMaterial()
			Material* temp = const_cast<Material*>(matTemplate.ptr());

			u32 numPasses = temp->getNumPass();

			for(u32 i = 0; i < numPasses; i++)
			{
				RenderPass* rp = temp->_getPass(i);
				RenderPass* rpNew = newMat->createPass(rp);
			}

			mat = newMat;

			mMaterialMap.insert(MapPair<_string, MaterialPtr>(cloneOneName, mat));
		}

		return mat;
	}

	void MaterialManager::removeAll()
	{
		for(MaterialNameMap::iterator it = mMaterialMap.begin(); it != mMaterialMap.end(); it++)
		{
			it->second.release();
		}

		mMaterialMap.clear();

		for(int i = 0; i < DST_NUM; i++)
		{
			mDefaultMats[i].release();
		}
	}

	void MaterialManager::_garbageDispose()
	{
		for(MaterialNameMap::iterator it = mMaterialMap.begin(); it != mMaterialMap.end(); )
		{
			if(it->second->getRefCount() == 1)
			{
                // 注意这里，erase是返回void类型
				mMaterialMap.erase(it++);
			}
			else
			{
				it++;
			}
		}
	}


}//end namespace Nezha